package com.hsc.www.amqp.config;


import com.hsc.www.amqp.annotation.TransMessage;
import com.hsc.www.amqp.util.RabbitMetaMessage;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * 描述：封装sender
 *
 * @author fw
 * 创建时间：2017年10月14日 下午10:30:00
 * @version 1.0.0
 */
@Component
@Aspect
public class TransactionSender {
    Logger logger = LoggerFactory.getLogger(TransactionSender.class);

    @Autowired
    RabbitSender rabbitSender;

    @Autowired
    MessageTransientStore messageTransientStore;

    @Autowired
    MessageDurableStore messageDurableStore;

    /**
     * 定义注解类型的切点，只要方法上有该注解，都会匹配
     */
    @Pointcut("@annotation(com.hsc.www.amqp.annotation.TransMessage)")
    public void annotationSender() {

    }

    @Around("annotationSender()&& @annotation(transMessage)")
    public void sendMsg(ProceedingJoinPoint joinPoint, TransMessage transMessage) throws Throwable {

        RabbitMetaMessage message = new RabbitMetaMessage();
        message.setMessageId(UUID.randomUUID().toString());
        message.setExchange(transMessage.exchange());
        message.setRoutingKey(transMessage.routingkey());
        message.setBizName(transMessage.bizName());
        message.setPrepareSendTime(new Date());

        int payloadIndex = transMessage.payloadIndex();
        if (payloadIndex > joinPoint.getArgs().length - 1 || payloadIndex < -1) {
            throw new RuntimeException("payloadIndex  错误！");
        }

        /**发送前暂存消息,这里payload暂存的是所有方法参数*/
        message.setPayload(joinPoint.getArgs());//
        messageTransientStore.saveMessage(message);

        /** 执行业务函数 */
        try {
            Object returnObj = joinPoint.proceed();
            if (payloadIndex == -1) {
                message.setPayload(returnObj);
            }else{
                message.setPayload(joinPoint.getArgs()[payloadIndex]);
            }
        } catch (Exception e) {
            messageTransientStore.removeMessage(message.getMessageId());
            throw e;
        }

        /** 发送消息 */
        try {
            message.setSendTime(new Date());
            //即使 send 没有抛出异常，也不能代表消息没有丢失
            rabbitSender.send(message);
        } catch (Exception e) {
            messageDurableStore.saveMessage(message, false, e.getMessage());
            messageTransientStore.removeMessage(message.getMessageId());
            throw e;
        }
    }

}
